/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.service.evaluation;

import cn.ac.nercis.pes.common.constant.evaluation.EvaluationModule;
import cn.ac.nercis.pes.common.constant.knowledge.AssetClassification;
import cn.ac.nercis.pes.common.constant.knowledge.LayerTarget;
import cn.ac.nercis.pes.common.constant.knowledge.TargetDeepness;
import cn.ac.nercis.pes.common.constant.knowledge.VirtualClassification;
import cn.ac.nercis.pes.common.constant.project.FinishState;
import cn.ac.nercis.pes.model.dto.common.Result;
import cn.ac.nercis.pes.model.dto.evaluation.asset.*;
import cn.ac.nercis.pes.model.dto.evaluation.content.BusinessConditionDTO;
import cn.ac.nercis.pes.model.dto.evaluation.content.NetworkTopologyDTO;
import cn.ac.nercis.pes.model.dto.evaluation.content.PasswordConditionDTO;
import cn.ac.nercis.pes.model.dto.evaluation.content.ToolCheckPointDTO;
import cn.ac.nercis.pes.repository.dal.evaluation.EvaluationRecordRepository;
import cn.ac.nercis.pes.repository.dal.evaluation.OverallEvaluationRepository;
import cn.ac.nercis.pes.repository.dal.evaluation.UnitEvaluationRepository;
import cn.ac.nercis.pes.repository.dal.evaluation.UnitRiskAnalysisRepository;
import cn.ac.nercis.pes.repository.dal.project.SystemTargetRepository;
import cn.ac.nercis.pes.repository.mapper.evaluation.AssetMapper;
import cn.ac.nercis.pes.repository.model.evaluation.AssetDO;
import cn.ac.nercis.pes.repository.model.evaluation.EvaluationRecordDO;
import cn.ac.nercis.pes.repository.model.evaluation.UnitEvaluationDO;
import cn.ac.nercis.pes.repository.model.project.SystemTargetDO;
import cn.ac.nercis.pes.service.project.SystemProcessService;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 资产变量应用服务
 * @author zpy
 * @version 1.0.0
 */
@Slf4j
@Service
public class AssetVariableApplyService {

    private final EvaluationContentService evaluationContentService;
    private final SystemProcessService systemProcessService;
    private final SystemTargetRepository systemTargetRepository;
    private final EvaluationRecordRepository evaluationRecordRepository;
    private final UnitEvaluationRepository unitEvaluationRepository;
    private final UnitRiskAnalysisRepository riskAnalysisRepository;
    private final OverallEvaluationRepository overallEvaluationRepository;

    @Autowired
    public AssetVariableApplyService(EvaluationContentService evaluationContentService,
                                     SystemProcessService systemProcessService,
                                     SystemTargetRepository systemTargetRepository,
                                     EvaluationRecordRepository evaluationRecordRepository,
                                     UnitEvaluationRepository unitEvaluationRepository,
                                     UnitRiskAnalysisRepository riskAnalysisRepository,
                                     OverallEvaluationRepository overallEvaluationRepository) {
        this.evaluationContentService = evaluationContentService;
        this.systemProcessService = systemProcessService;
        this.systemTargetRepository = systemTargetRepository;
        this.evaluationRecordRepository = evaluationRecordRepository;
        this.unitEvaluationRepository = unitEvaluationRepository;
        this.riskAnalysisRepository = riskAnalysisRepository;
        this.overallEvaluationRepository = overallEvaluationRepository;
    }

    public void assetVariableSync(AssetDO oldAsset, AssetDO newAsset, AssetService assetService){
        if(Objects.isNull(oldAsset) || Objects.isNull(newAsset)){
            return;
        }
        AssetClassification classification = AssetClassification.fromId(oldAsset.getClassId());
        switch (classification) {
            case PHY_ENV ->
                    this.phyEnvAssetSync(oldAsset.getSystemId(), AssetMapper.INSTANCE.toPhyEnvDTO(oldAsset), AssetMapper.INSTANCE.toPhyEnvDTO(newAsset), assetService);
            case PHY_SECURITY ->
                    this.phySecurityAssetSync(oldAsset.getSystemId(), AssetMapper.INSTANCE.toPhySecurity(oldAsset), AssetMapper.INSTANCE.toPhySecurity(newAsset));
            case PWD_PRODUCT ->
                    this.pwdProductAssetSync(oldAsset.getSystemId(), AssetMapper.INSTANCE.toPwdProduct(oldAsset), AssetMapper.INSTANCE.toPwdProduct(newAsset),assetService);
            case SERVER_STORAGE ->
                    this.serverStorageAssetSync(oldAsset.getSystemId(), AssetMapper.INSTANCE.toServerStorage(oldAsset), AssetMapper.INSTANCE.toServerStorage(newAsset));
            case NETWORK_SECURITY ->
                    this.networkSecurityAssetSync(oldAsset.getSystemId(), AssetMapper.INSTANCE.toNetworkSecurity(oldAsset), AssetMapper.INSTANCE.toNetworkSecurity(newAsset),assetService);
            case DATABASE ->
                    this.databaseAssetSync(oldAsset.getSystemId(), AssetMapper.INSTANCE.toDatabase(oldAsset), AssetMapper.INSTANCE.toDatabase(newAsset));
            case KEY_BUSINESS ->
                    this.keyBusinessAssetSync(oldAsset.getSystemId(), AssetMapper.INSTANCE.toKeyBusiness(oldAsset), AssetMapper.INSTANCE.toKeyBusiness(newAsset),assetService);
            case COMMUNICATION_CHANNEL ->
                    this.channelAssetSync(oldAsset.getSystemId(), AssetMapper.INSTANCE.toChannel(oldAsset), AssetMapper.INSTANCE.toChannel(newAsset));
            default -> {
            }
        }
    }

    private void phyEnvAssetSync(@NonNull String systemId, @NonNull PhyEnvDTO oldAsset, @NonNull PhyEnvDTO newAsset, AssetService assetService){
        if(!StringUtils.equals(oldAsset.getName(),newAsset.getName())){
            businessConditionApply(systemId,oldAsset.getName(),newAsset.getName());
            passwordConditionApply(systemId,oldAsset.getName(),newAsset.getName(),
                    true,true,false,false);
            pwdProductAssetApply(systemId,oldAsset.getName(),newAsset.getName(),assetService);
            channelAssetApply(systemId,oldAsset.getName(),newAsset.getName(),assetService);
            evaluationRecordApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV,LayerTarget.NET_COMMUNICATION);
            unitEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV);
            riskAnalysisApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV,LayerTarget.NET_COMMUNICATION);
            overallEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV,LayerTarget.NET_COMMUNICATION);
        }
        if(!StringUtils.equals(oldAsset.getLocation(),newAsset.getLocation())){
            unitEvaluationApply(systemId,oldAsset.getLocation(),newAsset.getLocation(),
                    LayerTarget.PHY_ENV);
            riskAnalysisApply(systemId,oldAsset.getLocation(),newAsset.getLocation(),
                    LayerTarget.PHY_ENV);
            overallEvaluationApply(systemId,oldAsset.getLocation(),newAsset.getLocation(),
                    LayerTarget.PHY_ENV);
        }
    }

    private void phySecurityAssetSync(@NonNull String systemId, @NonNull PhySecurityDTO oldAsset, @NonNull PhySecurityDTO newAsset){
        if(!StringUtils.equals(oldAsset.getName(),newAsset.getName())){
            passwordConditionApply(systemId,oldAsset.getName(),newAsset.getName(),
                    true,false,false,false);
            evaluationRecordApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV);
            unitEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV);
            riskAnalysisApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV);
            overallEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV);
        }
        if(!StringUtils.equals(oldAsset.getVendor(),newAsset.getVendor())){
            passwordConditionApply(systemId,oldAsset.getVendor(),newAsset.getVendor(),
                    true,false,false,false);
            unitEvaluationApply(systemId,oldAsset.getVendor(),newAsset.getVendor(),
                    LayerTarget.PHY_ENV);
        }
    }

    private void pwdProductAssetSync(@NonNull String systemId, @NonNull PwdProductDTO oldAsset, @NonNull PwdProductDTO newAsset, AssetService assetService){
        if(!StringUtils.equals(oldAsset.getName(),newAsset.getName())){
            passwordConditionApply(systemId,oldAsset.getName(),newAsset.getName(),
                    false,true,true,true);
            pwdProductAssetApply(systemId,oldAsset.getName(),newAsset.getName(),assetService);
            channelAssetApply(systemId,oldAsset.getName(),newAsset.getName(),assetService);
            toolCheckPointApply(systemId,oldAsset.getName(),newAsset.getName());

            evaluationRecordApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV,LayerTarget.NET_COMMUNICATION,LayerTarget.DEVICE_COMPUTE,LayerTarget.APP_DATA);
            unitEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.NET_COMMUNICATION,LayerTarget.DEVICE_COMPUTE,LayerTarget.APP_DATA);
            riskAnalysisApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.APP_DATA);
            overallEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.NET_COMMUNICATION,LayerTarget.DEVICE_COMPUTE);
        }
        if(!StringUtils.equals(oldAsset.getVendor(),newAsset.getVendor())){
            passwordConditionApply(systemId,oldAsset.getVendor(),newAsset.getVendor(),
                    false,false,false,true);

            evaluationRecordApply(systemId,oldAsset.getVendor(),newAsset.getVendor(),
                    LayerTarget.DEVICE_COMPUTE,LayerTarget.APP_DATA);
            unitEvaluationApply(systemId,oldAsset.getVendor(),newAsset.getVendor(),
                    LayerTarget.DEVICE_COMPUTE,LayerTarget.APP_DATA);
            riskAnalysisApply(systemId,oldAsset.getVendor(),newAsset.getVendor(),
                    LayerTarget.APP_DATA);
        }
        if(!StringUtils.equals(oldAsset.getModel(),newAsset.getModel())){
            unitEvaluationApply(systemId,oldAsset.getModel(),newAsset.getModel(),
                    LayerTarget.DEVICE_COMPUTE);
        }
        if(!StringUtils.equals(oldAsset.getAlgorithm(),newAsset.getAlgorithm())){
            evaluationRecordApply(systemId,oldAsset.getAlgorithm(),newAsset.getAlgorithm(),
                    LayerTarget.NET_COMMUNICATION,LayerTarget.DEVICE_COMPUTE,LayerTarget.APP_DATA);
            unitEvaluationApply(systemId,oldAsset.getAlgorithm(),newAsset.getAlgorithm(),
                    LayerTarget.NET_COMMUNICATION,LayerTarget.DEVICE_COMPUTE,LayerTarget.APP_DATA);
            riskAnalysisApply(systemId,oldAsset.getAlgorithm(),newAsset.getAlgorithm(),
                    LayerTarget.NET_COMMUNICATION);
        }
    }

    private void serverStorageAssetSync(@NonNull String systemId, @NonNull ServerStorageDTO oldAsset, @NonNull ServerStorageDTO newAsset){
        if(!StringUtils.equals(oldAsset.getName(),newAsset.getName())){
            networkTopologyApply(systemId,oldAsset.getName(),newAsset.getName());
            passwordConditionApply(systemId,oldAsset.getName(),oldAsset.getName(),
                    false,false,true,true);
            evaluationRecordApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.DEVICE_COMPUTE);
            unitEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.DEVICE_COMPUTE);
            riskAnalysisApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.DEVICE_COMPUTE);
            overallEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.DEVICE_COMPUTE);
        }
        if(!StringUtils.equals(oldAsset.getOsName(),newAsset.getOsName())){
            evaluationRecordApply(systemId,oldAsset.getOsName(),newAsset.getOsName(),
                    LayerTarget.DEVICE_COMPUTE);
            riskAnalysisApply(systemId,oldAsset.getOsName(),newAsset.getOsName(),
                    LayerTarget.DEVICE_COMPUTE);
        }
    }

    private void networkSecurityAssetSync(@NonNull String systemId, @NonNull NetworkSecurityDTO oldAsset, @NonNull NetworkSecurityDTO newAsset,
                                          AssetService assetService){
        if(!StringUtils.equals(oldAsset.getName(),newAsset.getName())){
            networkTopologyApply(systemId,oldAsset.getName(),newAsset.getName());
            passwordConditionApply(systemId,oldAsset.getName(),oldAsset.getName(),
                    false,false,true,true);
            channelAssetApply(systemId,oldAsset.getName(),oldAsset.getName(),assetService);

            evaluationRecordApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.NET_COMMUNICATION,LayerTarget.DEVICE_COMPUTE);
            unitEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.NET_COMMUNICATION,LayerTarget.DEVICE_COMPUTE);
            riskAnalysisApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.NET_COMMUNICATION,LayerTarget.DEVICE_COMPUTE);
            overallEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.NET_COMMUNICATION,LayerTarget.DEVICE_COMPUTE);
        }
    }

    private void databaseAssetSync(@NonNull String systemId, @NonNull DatabaseDTO oldAsset, @NonNull DatabaseDTO newAsset){
        if(!StringUtils.equals(oldAsset.getName(),newAsset.getName())){
            riskAnalysisApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.DEVICE_COMPUTE);
        }
        if(!StringUtils.equals(oldAsset.getVersion(),newAsset.getVersion())){
            evaluationRecordApply(systemId,oldAsset.getVersion(),newAsset.getVersion(),
                    LayerTarget.DEVICE_COMPUTE);
        }
    }

    private void keyBusinessAssetSync(@NonNull String systemId, @NonNull KeyBusinessDTO oldAsset, @NonNull KeyBusinessDTO newAsset,
                                      AssetService assetService){
        if(!StringUtils.equals(oldAsset.getName(),newAsset.getName())){
            passwordConditionApply(systemId,oldAsset.getName(),oldAsset.getName(),
                    false,true,false,true);
            channelAssetApply(systemId,oldAsset.getName(),newAsset.getName(),assetService);

            evaluationRecordApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV,LayerTarget.NET_COMMUNICATION,LayerTarget.APP_DATA);

            unitEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV,LayerTarget.NET_COMMUNICATION,LayerTarget.APP_DATA);
            riskAnalysisApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV,LayerTarget.APP_DATA);
            overallEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.PHY_ENV,LayerTarget.NET_COMMUNICATION,LayerTarget.APP_DATA);
        }
    }

    private void channelAssetSync(@NonNull String systemId, @NonNull ChannelDTO oldAsset, @NonNull ChannelDTO newAsset){
        if(!StringUtils.equals(oldAsset.getName(),newAsset.getName())){
            passwordConditionApply(systemId,oldAsset.getName(),oldAsset.getName(),
                    false,true,false,false);
            evaluationRecordApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.NET_COMMUNICATION);
            unitEvaluationApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.NET_COMMUNICATION);
            riskAnalysisApply(systemId,oldAsset.getName(),newAsset.getName(),
                    LayerTarget.NET_COMMUNICATION);
        }
    }




    private void businessConditionApply(@NonNull String systemId,String oldContent,String newContent){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        BusinessConditionDTO businessCondition = this.evaluationContentService.findBusinessCondition(systemId);
        if(StringUtils.contains(businessCondition.getContent(),oldContent)){
            businessCondition.setContent(StringUtils.replace(businessCondition.getContent(),oldContent,newContent));
            Result<String> result = this.evaluationContentService.saveBusinessCondition(systemId, businessCondition);
            if(result.isSuccess()){
                systemProcessService.setSystemProcess(systemId, EvaluationModule.BUSINESS, FinishState.INCOMPLETE);
            }
        }
    }

    private void passwordConditionApply(@NonNull String systemId,String oldContent,String newContent,
                                        boolean phyEnvApply,boolean netCommunicationApply,
                                        boolean deviceComputeApply,boolean appDataApply){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        PasswordConditionDTO passwordCondition = this.evaluationContentService.findPasswordCondition(systemId);
        boolean isChange =false;
        if(phyEnvApply && StringUtils.contains(passwordCondition.getPhyEnv(),oldContent)){
            passwordCondition.setPhyEnv(StringUtils.replace(passwordCondition.getPhyEnv(),oldContent,newContent));
            isChange = true;
        }
        if(netCommunicationApply && StringUtils.contains(passwordCondition.getNetCommunication(),oldContent)){
            passwordCondition.setNetCommunication(StringUtils.replace(passwordCondition.getNetCommunication(),oldContent,newContent));
            isChange = true;
        }
        if(deviceComputeApply && StringUtils.contains(passwordCondition.getDeviceCompute(),oldContent)){
            passwordCondition.setDeviceCompute(StringUtils.replace(passwordCondition.getDeviceCompute(),oldContent,newContent));
            isChange = true;
        }
        if(appDataApply && StringUtils.contains(passwordCondition.getAppData(),oldContent)){
            passwordCondition.setAppData(StringUtils.replace(passwordCondition.getAppData(),oldContent,newContent));
            isChange = true;
        }
        if(isChange){
            Result<String> result = this.evaluationContentService.savePasswordCondition(systemId,passwordCondition);
            if(result.isSuccess()){
                systemProcessService.setSystemProcess(systemId, EvaluationModule.PASSWORD_USE, FinishState.INCOMPLETE);
            }
        }
    }

    private void pwdProductAssetApply(@NonNull String systemId,String oldContent,String newContent, AssetService assetService){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        List<PwdProductDTO> assets = assetService.findPwdProduct("",systemId);
        List<PwdProductDTO> modifyAssets = assets.stream()
                .filter(pp->StringUtils.contains(pp.getUse(),oldContent))
                .peek(pp-> pp.setUse(StringUtils.replace(pp.getUse(),oldContent,newContent)))
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(modifyAssets)){
            assetService.batchSavePwdProduct(systemId,modifyAssets);
            systemProcessService.setSystemProcess(systemId, EvaluationModule.ASSET_PWD_PRODUCT, FinishState.INCOMPLETE);
        }
    }

    private void channelAssetApply(@NonNull String systemId,String oldContent,String newContent, AssetService assetService){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        List<ChannelDTO> assets = assetService.findChannel("",systemId);
        List<ChannelDTO> modifyAssets = assets.stream()
                .filter(pp->StringUtils.contains(pp.getName(),oldContent))
                .peek(pp-> pp.setName(StringUtils.replace(pp.getName(),oldContent,newContent)))
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(modifyAssets)){
            assetService.batchSaveChannel(systemId,modifyAssets);
            systemProcessService.setSystemProcess(systemId, EvaluationModule.ASSET_COMMUNICATION_CHANNEL, FinishState.INCOMPLETE);
        }
    }

    private void networkTopologyApply(@NonNull String systemId,String oldContent,String newContent){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        NetworkTopologyDTO networkTopology = this.evaluationContentService.findNetworkTopology(systemId);
        boolean isChange = false;
        if(StringUtils.contains(networkTopology.getZoneSummary(),oldContent)){
            networkTopology.setZoneSummary(StringUtils.replace(networkTopology.getZoneSummary(),oldContent,newContent));
            isChange = true;
        }
        if(StringUtils.contains(networkTopology.getZoneIllustrate(),oldContent)){
            networkTopology.setZoneIllustrate(StringUtils.replace(networkTopology.getZoneIllustrate(),oldContent,newContent));
            isChange = true;
        }
        if(isChange){
            Result<String> result = this.evaluationContentService.saveNetworkTopology(systemId,networkTopology);
            if(result.isSuccess()){
                systemProcessService.setSystemProcess(systemId, EvaluationModule.NETWORK_TOPOLOGY, FinishState.INCOMPLETE);
            }
        }
    }

    private void toolCheckPointApply(@NonNull String systemId, String oldContent,String newContent){
        this.toolCheckPointApply(systemId,oldContent,newContent,true);
    }

    private void toolCheckPointApply(@NonNull String systemId,String oldContent,String newContent,
                                     @NonNull Boolean replace){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        ToolCheckPointDTO toolCheckPoint = this.evaluationContentService.findToolCheckPoint(systemId);
        if(StringUtils.contains(toolCheckPoint.getDesc(),oldContent)){
            if(replace){
                toolCheckPoint.setDesc(StringUtils.replace(toolCheckPoint.getDesc(),oldContent,newContent));
                Result<String> result = this.evaluationContentService.saveToolCheckPoint(systemId,toolCheckPoint);
                if(result.isSuccess()){
                    systemProcessService.setSystemProcess(systemId, EvaluationModule.METHOD_TOOL, FinishState.INCOMPLETE);
                }
            }else{
                systemProcessService.setSystemProcess(systemId, EvaluationModule.METHOD_TOOL, FinishState.INCOMPLETE);
            }
        }
    }
    private void evaluationRecordApply(@NonNull String systemId,String oldContent,String newContent,
                                       LayerTarget... layerTargets){
        evaluationRecordApply(systemId,oldContent,newContent,true,layerTargets);
    }
    private void evaluationRecordApply(@NonNull String systemId,String oldContent,String newContent,
                                       @NonNull Boolean replace,LayerTarget... layerTargets){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        Set<String> layerTargetIds = findLayerTargetIds(systemId,layerTargets);
        List<EvaluationRecordDO> modifyRecords = evaluationRecordRepository.findAllBySystemIdAndLayerTargetIdIn(systemId,layerTargetIds)
                .stream()
                .filter(er->StringUtils.contains(er.getDContent(),oldContent)
                        || StringUtils.contains(er.getAContent(),oldContent)
                        || StringUtils.contains(er.getKContent(),oldContent)
                        || StringUtils.contains(er.getContent(),oldContent))
                .peek(er->{
                    if(replace && StringUtils.contains(er.getDContent(),oldContent)){
                        er.setDContent(StringUtils.replace(er.getDContent(),oldContent,newContent));
                    }
                    if(replace && StringUtils.contains(er.getAContent(),oldContent)){
                        er.setAContent(StringUtils.replace(er.getAContent(),oldContent,newContent));
                    }
                    if(replace && StringUtils.contains(er.getKContent(),oldContent)){
                        er.setKContent(StringUtils.replace(er.getKContent(),oldContent,newContent));
                    }
                    if(replace && StringUtils.contains(er.getContent(),oldContent)){
                        er.setContent(StringUtils.replace(er.getContent(),oldContent,newContent));
                    }
                    er.setFinishState(FinishState.INCOMPLETE);
                })
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(modifyRecords)){
            this.evaluationRecordRepository.saveAll(modifyRecords);
            modifyRecords.stream()
                    .filter(er->Objects.nonNull(er.getAsset()))
                    .map(er-> VirtualClassification.fromClassId(er.getAsset().getClassId()))
                    .filter(Objects::nonNull)
                    .distinct()
                    .forEach(vc-> systemProcessService.setSystemProcess(systemId,
                            EvaluationModule.fromNameByScene(vc.getName()),
                            FinishState.INCOMPLETE));
        }
    }
    private void unitEvaluationApply(@NonNull String systemId,String oldContent,String newContent,
                                     LayerTarget... layerTargets){
        unitEvaluationApply(systemId,oldContent,newContent,true,layerTargets);
    }
    private void unitEvaluationApply(@NonNull String systemId,String oldContent,String newContent,
                                     @NonNull Boolean replace,LayerTarget... layerTargets){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        var layerTargetInfos = findLayerTarget(systemId,layerTargets);
        Set<String> layerTargetIds = layerTargetInfos.stream().map(SystemTargetDO::getKmTargetId).collect(Collectors.toSet());
        List<UnitEvaluationDO> modifyData = unitEvaluationRepository.findAllBySystemIdAndLayerTargetIdIn(systemId, layerTargetIds)
                .stream()
                .filter(ue -> StringUtils.contains(ue.getResultAnalysis(), oldContent))
                .peek(ue->{
                    if(replace && StringUtils.contains(ue.getResultAnalysis(),oldContent)){
                        ue.setResultAnalysis(StringUtils.replace(ue.getResultAnalysis(),oldContent,newContent));
                    }
                    ue.setFinishState(FinishState.INCOMPLETE);
                })
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(modifyData)){
            this.unitEvaluationRepository.saveAll(modifyData);
            modifyData.stream()
                    .flatMap(ue->layerTargetInfos.stream()
                            .filter(lt->StringUtils.equals(lt.getId(),ue.getLayerTargetId())))
                    .map(SystemTargetDO::getKmName)
                    .distinct()
                    .forEach(name->systemProcessService.setSystemProcess(systemId,
                            EvaluationModule.fromNameByUnitEval(name),
                            FinishState.INCOMPLETE));
        }
    }

    private void riskAnalysisApply(@NonNull String systemId,String oldContent,String newContent,
                                   LayerTarget... layerTargets){
        riskAnalysisApply(systemId,oldContent,newContent,true,layerTargets);
    }

    private void riskAnalysisApply(@NonNull String systemId,String oldContent,String newContent,
                                   @NonNull Boolean replace,LayerTarget... layerTargets){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        var layerTargetInfos = findLayerTarget(systemId,layerTargets);
        Set<String> layerTargetIds = layerTargetInfos.stream().map(SystemTargetDO::getKmTargetId).collect(Collectors.toSet());
        var modifyData = riskAnalysisRepository.findAllBySystemIdAndLayerTargetIdIn(systemId,layerTargetIds)
                .stream()
                .filter(ra->StringUtils.contains(ra.getProblem(),oldContent)
                        || StringUtils.contains(ra.getSuggest(),oldContent)
                        || StringUtils.contains(ra.getAnalysis(),oldContent))
                .peek(ra->{
                    if(replace && StringUtils.contains(ra.getProblem(),oldContent)){
                        ra.setProblem(StringUtils.replace(ra.getProblem(),oldContent,newContent));
                    }
                    if(replace && StringUtils.contains(ra.getSuggest(),oldContent)){
                        ra.setSuggest(StringUtils.replace(ra.getSuggest(),oldContent,newContent));
                    }
                    if(replace && StringUtils.contains(ra.getAnalysis(),oldContent)){
                        ra.setAnalysis(StringUtils.replace(ra.getAnalysis(),oldContent,newContent));
                    }
                })
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(modifyData)){
            this.riskAnalysisRepository.saveAll(modifyData);
            modifyData.stream()
                    .flatMap(ue->layerTargetInfos.stream()
                            .filter(lt->StringUtils.equals(lt.getId(),ue.getLayerTargetId())))
                    .map(SystemTargetDO::getKmName)
                    .distinct()
                    .forEach(name->systemProcessService.setSystemProcess(systemId,
                            EvaluationModule.fromNameByRiskAnalysis(name),
                            FinishState.INCOMPLETE));
        }
    }

    private void overallEvaluationApply(@NonNull String systemId,String oldContent,String newContent,
                                        LayerTarget... layerTargets){
        overallEvaluationApply(systemId,oldContent,newContent,true,layerTargets);
    }

    private void overallEvaluationApply(@NonNull String systemId,String oldContent,String newContent,
                                        @NonNull Boolean replace,LayerTarget... layerTargets){
        if(StringUtils.isBlank(oldContent) || StringUtils.equals(oldContent,newContent)){
            return;
        }
        var layerTargetInfos = findLayerTarget(systemId,layerTargets);
        Set<String> layerTargetIds = layerTargetInfos.stream().map(SystemTargetDO::getKmTargetId).collect(Collectors.toSet());
        var modifyData = overallEvaluationRepository.findAllBySystemIdAndLayerTargetIdIn(systemId,layerTargetIds)
                .stream()
                .filter(oe->StringUtils.contains(oe.getContent(),oldContent))
                .peek(oe->{
                    if(replace){
                        oe.setContent(StringUtils.replace(oe.getContent(),oldContent,newContent));
                    }
                    oe.setFinishState(FinishState.INCOMPLETE);
                })
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(modifyData)){
            this.overallEvaluationRepository.saveAll(modifyData);
            modifyData.stream()
                    .flatMap(ue->layerTargetInfos.stream().filter(lt->StringUtils.equals(lt.getId(),ue.getLayerTargetId())))
                    .map(SystemTargetDO::getKmName)
                    .distinct()
                    .forEach(name->systemProcessService.setSystemProcess(systemId,
                            EvaluationModule.fromNameByOverallAppraise(name),
                            FinishState.INCOMPLETE));
        }
    }

    private Set<String> findLayerTargetIds(String systemId, LayerTarget... layerTargets){
        var layerTargetNames = Arrays.stream(layerTargets)
                .map(LayerTarget::getName)
                .toList();
        return this.systemTargetRepository.findAllBySystemId(systemId)
                .stream()
                .filter(st->st.getKmDeepness() == TargetDeepness.LAYER.getDeepness()
                        && layerTargetNames.stream().anyMatch(tn->StringUtils.equals(tn,st.getKmName())))
                .map(SystemTargetDO::getKmTargetId)
                .collect(Collectors.toSet());
    }

    private List<SystemTargetDO> findLayerTarget(String systemId, LayerTarget... layerTargets){
        List<String> layerTargetNames = Arrays.stream(layerTargets)
                .map(LayerTarget::getName)
                .toList();
        return this.systemTargetRepository.findAllBySystemId(systemId)
                .stream()
                .filter(st->st.getKmDeepness() == TargetDeepness.LAYER.getDeepness()
                        && layerTargetNames.stream().anyMatch(tn->StringUtils.equals(tn,st.getKmName())))
                .collect(Collectors.toList());
    }

}